export function notNullOrUndefined<T>(value: T | null | undefined): value is NonNullable<T> {
	return value !== undefined && value !== null;
}

export function takeIf<V, T>(exp: V | null | undefined, action: (value: NonNullable<V>) => T): T | undefined {
	if (notNullOrUndefined(exp)) {
		return action(exp);
	}
}

export function clone<T>(value: T): T {
	if (value instanceof Date) {
		return new Date(value) as T;
	} else if (value instanceof Array) {
		return value.map((v) => clone(v)) as T;
	} else if (typeof value === 'object') {
		const newValue: Record<string, unknown> = {};
		Object.getOwnPropertyNames(value).forEach((k) => {
			newValue[k] = clone((value as Record<string, unknown>)[k]);
		});
		return newValue as T;
	} else {
		return value;
	}
}
